/*
 * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
 * Licensed under the MIT License, (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://opensource.org/licenses/MIT
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Subscription } from './Subscription';
import { BusRuntime } from '../bus/BusRuntime';
import { MethodParameters } from '../entry/MethodParameters';
import { SubscriptionContext } from './SubscriptionContext';
import type { IMessageDispatcher } from '../dispatch/IMessageDispatcher';
import { FilteredMessageDispatcher } from '../dispatch/FilteredMessageDispatcher';
import { MessageDispatcher } from '../dispatch/MessageDispatcher';
import type { IHandlerInvocation } from '../dispatch/IHandlerInvocation';
import { AsynchronousHandlerInvocation } from '../dispatch/AsynchronousHandlerInvocation';
import { SynchronizedHandlerInvocation } from '../dispatch/SynchronizedHandlerInvocation';
import { LogUtil } from '../../../../utils/LogUtil';

export class SubscriptionFactory {
  createSubscription(runtime: BusRuntime, parameters: MethodParameters, isStrong: boolean): Subscription {
    LogUtil.info(`Creating subscription with isStrong: ${isStrong}`);
    let context = new SubscriptionContext(runtime, parameters);
    let invocation = this.buildInvocationForHandler(context);
    let dispatch = this.buildDispatcher(context, invocation);
    return new Subscription(context, dispatch, isStrong);
  }

  buildDispatcher(context: SubscriptionContext, invocation: IHandlerInvocation): IMessageDispatcher {
    LogUtil.info('Building message dispatcher');
    let dispatcher: IMessageDispatcher;
    let isFiltered = context.getHandleParameters().isFiltered();
    if (isFiltered) {
      LogUtil.debug('Creating filtered message dispatcher');
      dispatcher = new FilteredMessageDispatcher(context, invocation);
    }
    if (!dispatcher) {
      LogUtil.debug('Creating default message dispatcher');
      dispatcher = new MessageDispatcher(context, invocation);
    }
    return dispatcher;
  }

  buildInvocationForHandler(context: SubscriptionContext): IHandlerInvocation {
    LogUtil.info('Building handler invocation');
    let invocation: IHandlerInvocation;
    if (context.getHandleParameters().isAsynchronous()) {
      LogUtil.debug('Creating asynchronous handler invocation');
      invocation = new AsynchronousHandlerInvocation();
    } else {
      LogUtil.debug('Creating synchronized handler invocation');
      invocation = new SynchronizedHandlerInvocation();
    }
    return invocation;
  }
}